
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>6、NIO中的ByteBuffer - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>6、NIO中的ByteBuffer - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">ByteBuffer 的三个核心属性是什么？它们分别代表什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">三个核心属性是 capacity、position 和 limit。capacity 是缓冲区的最大容量，创建后不可改变；position 是当前读/写操作的位置，操作后会自动前进；limit 是可访问数据的边界，在写模式下等于capacity，在读模式下等于已写入的数据量。</div>
          </div>
          <div class="card-source">来源: 1.2 Buffer的核心属性</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在ByteBuffer中，`flip()` 方法的具体作用是什么？它通常在什么操作之后被调用？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`flip()` 方法用于将缓冲区从写模式切换到读模式。它将 limit 设置为当前的 position 值，然后将 position 重置为 0。这使得程序可以从缓冲区的开头开始读取刚刚写入的所有数据。它通常在向缓冲区写入数据后、准备读取数据前被调用。</div>
          </div>
          <div class="card-source">来源: 2.3 rewind、flip和clear</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">创建ByteBuffer的 `allocate()` 和 `allocateDirect()` 方法有何主要区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别在于内存分配的位置。`allocate()` 在JVM堆上分配内存，创建的是非直接缓冲区（堆缓冲区）。而 `allocateDirect()` 分配的是直接内存（堆外内存）。在进行I/O操作时，直接缓冲区可以避免一次从JVM堆到本地堆的数据拷贝，因此在频繁进行网络或文件I/O操作时性能更高。</div>
          </div>
          <div class="card-source">来源: 3.1 直接缓冲区（Direct Buffer）与非直接缓冲区</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请解释 `ByteBuffer` 的 `mark()` 和 `reset()` 方法的功能及其应用场景。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`mark()` 方法用于在当前 position 位置设置一个标记，而 `reset()` 方法可以将 position 恢复到之前标记的位置。这个组合在需要反复读取某段数据时非常有用，例如在解析网络协议时，可以先读取包头信息，标记位置，然后根据包头信息继续读取，如果需要，还可以通过 reset() 回到包头之后的位置重新处理。</div>
          </div>
          <div class="card-source">来源: 2.2 mark和reset</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">什么是字节序（Byte Order）？`ByteBuffer` 是如何支持不同字节序的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">字节序是指多字节数据类型（如int, long）在内存中存储的字节顺序，主要分为大端序（BIG_ENDIAN）和小端序（LITTLE_ENDIAN）。`ByteBuffer` 默认使用大端序，但可以通过调用 `order(ByteOrder)` 方法来显式设置其字节序，以确保在与不同平台进行数据交换时能够正确地解释数据。</div>
          </div>
          <div class="card-source">来源: 3.2 字节序（Byte Order）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">`ByteBuffer` 的 `compact()` 方法和 `clear()` 方法有什么不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`clear()` 方法将 position 设为0，limit 设为 capacity，为下一次写入做准备，但它并不会清除缓冲区内的数据。而 `compact()` 方法会将所有未读的数据（从当前 position 到 limit 之间的数据）移动到缓冲区的开头，然后将 position 设置在这些数据的末尾，limit 设为 capacity。它适用于处理完部分数据后，需要继续向缓冲区写入新数据的场景。</div>
          </div>
          <div class="card-source">来源: 2.3 rewind、flip和clear</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">什么是 `ByteBuffer` 的视图缓冲区（View Buffer）？它有什么优点？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">视图缓冲区允许将一个 `ByteBuffer` 的内容视为其他基本数据类型的缓冲区，例如 `IntBuffer` 或 `DoubleBuffer`。它与原始的 `ByteBuffer` 共享底层数据。其优点是能够以类型化的方式批量读写数据，简化了操作，提高了代码可读性和性能，避免了手动进行字节转换。</div>
          </div>
          <div class="card-source">来源: 3.3 视图缓冲区（View Buffer）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">除了 `allocate()` 和 `allocateDirect()`，还有什么常用的方式可以创建 `ByteBuffer`？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">还可以通过 `wrap()` 方法将一个已有的字节数组（byte[]）包装成一个 `ByteBuffer`。这种方式创建的缓冲区会使用该字节数组作为其后备存储，对缓冲区的修改会直接反映在原始数组中，反之亦然。这种方式在处理已存在的字节数据时非常高效，因为它避免了数据复制。</div>
          </div>
          <div class="card-source">来源: 1.3 ByteBuffer的创建方式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">应用</div>
          <div class="card-question">在NIO网络编程中，`ByteBuffer` 是如何与 `Channel` 和 `Selector` 协同工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">应用</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在NIO模型中，`ByteBuffer` 充当数据容器。数据通过 `Channel` 从网络或文件读入 `ByteBuffer`，或者从 `ByteBuffer` 写入 `Channel`。`Selector` 负责监控多个 `Channel` 的I/O事件（如连接、可读、可写）。当 `Selector` 检测到某个 `Channel` 可读时，应用程序就会使用 `channel.read(buffer)` 将数据读入 `ByteBuffer` 中进行处理。</div>
          </div>
          <div class="card-source">来源: 4.1 使用ByteBuffer进行网络编程</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
